View Javadoc
1   package edu.jiangxin.apktoolbox.file.password.recovery.category.bruteforce;
2   
3   import org.apache.logging.log4j.LogManager;
4   import org.apache.logging.log4j.Logger;
5   
6   import java.util.concurrent.ExecutionException;
7   import java.util.concurrent.Future;
8   import java.util.concurrent.TimeUnit;
9   import java.util.concurrent.TimeoutException;
10  import java.util.concurrent.atomic.AtomicInteger;
11  import java.util.concurrent.locks.Condition;
12  import java.util.concurrent.locks.Lock;
13  import java.util.concurrent.locks.ReentrantLock;
14  
15  public class BruteForceFuture implements Future<String> {
16      private static final Logger logger = LogManager.getLogger(BruteForceFuture.class.getSimpleName());
17      private volatile String result = null;
18      private final AtomicInteger finishedTaskCount = new AtomicInteger(0);
19      private final int taskCount;
20      private final Lock lock = new ReentrantLock();
21      private final Condition condition = lock.newCondition();
22  
23      private boolean isCancelled;
24  
25      public BruteForceFuture(int taskCount) {
26          this.taskCount = taskCount;
27      }
28  
29      public void set(String result) {
30          lock.lock();
31          logger.debug("set lock");
32          try {
33              if (result != null || finishedTaskCount.incrementAndGet() >= taskCount) {
34                  logger.info("set result: {}", result);
35                  // Sleep to avoid the thread running too fast, which may cause bruteForceFuture#get has not been called
36                  // Thus, condition.await maybe called after condition.signal
37                  try {
38                      Thread.sleep(1000);
39                  } catch (InterruptedException e) {
40                      logger.error("sleep InterruptedException");
41                      Thread.currentThread().interrupt();
42                  }
43                  this.result = result;
44                  condition.signal();
45              }
46          } finally {
47              logger.debug("set unlock");
48              lock.unlock();
49          }
50      }
51  
52      @Override
53      public String get() {
54          lock.lock();
55          logger.debug("get lock");
56          try {
57              condition.await();
58          } catch (InterruptedException e) {
59              logger.error("await InterruptedException");
60              Thread.currentThread().interrupt();
61          } finally {
62              logger.debug("get unlock");
63              lock.unlock();
64          }
65          return result;
66      }
67  
68      @Override
69      public boolean isDone() {
70          return result != null;
71      }
72  
73      @Override
74      public boolean cancel(boolean mayInterruptIfRunning) {
75          isCancelled = true;
76          return true;
77      }
78  
79      @Override
80      public boolean isCancelled() {
81          return isCancelled;
82      }
83  
84      @Override
85      public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
86          // no need to implement this. We don't use this...
87          return null;
88      }
89  }